/**
 * @file ThriftServer.hpp
 * @brief Thrift Client服务器
 */

#include <thrift/TToString.h>
#include <thrift/concurrency/ThreadFactory.h>
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>

#include <mutex>
#include <spdlog/spdlog.h>

#include "ControlCollege.hpp"
#include <ClientPub.hpp>
#include <NodeClient.h>
#include <functional>

/**
 * @class ThriftServer
 * @brief Thrift处理对象
 * @note 控制接口的详细描述参见`ControlCollege`
 */
class ThriftServer : public Thrift::NodeClientIf {
  ControlCollege *college;
  ClientPub *broadcast;
  std::string peerAddr;
  std::mutex bufMut;

public:
  /**
   * @brief 构造函数
   *
   * @param college_ 托管的`ControlCollege`对象指针
   * @param broadcast_ 广播对象
   * @param hostaddr 主机地址
   */
  ThriftServer(ControlCollege *college_, ClientPub *broadcast_,
               const std::string &hostaddr);
  /**
   * @brief 开始拍摄
   *
   * @param UUID 相机UUID
   */
  virtual void StartShot(const std::string &UUID) override;
  /**
   * @brief 停止拍摄
   *
   * @param UUID 相机UUID
   */
  virtual void StopShot(const std::string &UUID) override;
  /**
   * @brief 拍摄状态
   *
   * @param UUID 相机UUID
   * @return `true`正在拍摄,`false`没有拍摄
   */
  virtual bool ShotStatus(const std::string &UUID) override;
  /**
   * @brief 开始录制
   *
   * @param UUID 相机UUID
   * @param savepath 文件存储路径
   * @param format_index 格式索引
   */
  virtual void StartRecord(const std::string &UUID, const std::string &savepath,
                           const int16_t format_index) override;
  /**
   * @brief 停止录制
   *
   * @param UUID 相机UUID
   */
  virtual void StopRecord(const std::string &UUID) override;
  /**
   * @brief 录制状态
   *
   * @param UUID 相机UUID
   * @return `true`正在录制，`false`没有录制
   */
  virtual bool RecordStatus(const std::string &UUID) override;
  /**
   * @brief 获取所有设备
   *
   * @param _return 设备列表
   */
  virtual void GetAllDevice(std::set<std::string> &_return) override;
  /**
   * @brief 获取所有格式
   *
   * @param _return 格式列表（索引，名称）
   */
  virtual void GetAllFormat(std::map<int16_t, std::string> &_return) override;
  /**
   * @brief 获取参数列表
   *
   * @param _return 参数列表（JSON）
   * @param UUID 设备UUID
   */
  virtual void GetSettingList(std::string &_return,
                              const std::string &UUID) override;
  /**
   * @brief 获取设备参数
   *
   * @param _return 设备参数（JSON）
   * @param UUID 设备UUID
   * @param setid 设置编号
   */
  virtual void GetSettingValue(std::string &_return, const std::string &UUID,
                               const int32_t setid) override;
  /**
   * @brief 设置设备参数
   *
   * @param UUID 相机UUID
   * @param value 设置内容（JSON）
   * @return `true`设置成功，`false`设置失败
   */
  virtual bool SetSettingValue(const std::string &UUID,
                               const std::string &value) override;
  /**
   * @brief 获取共享内存信息
   *
   * @param _return 返回内存信息
   * @param UUID 相机UUID
   */
  virtual void GetShareMemInfo(std::string &_return,
                               const std::string &UUID) override;
  /**
   * @brief 请求设备下线
   *
   * @param UUID 设备UUID
   */
  virtual void OfflineCamera(const std::string &UUID) override;
  /**
   * @brief 开始拍摄回调函数
   */
  std::function<void(std::string uuid)> funcStartShot;
  /**
   * @brief 停止拍摄回调函数
   */
  std::function<void(std::string uuid)> funcStopShot;
  /**
   * @brief 获取预览图像信息
   *
   * @param _return JSON数据
   * @param uuid 相机UUID
   */
  virtual void GetPreviewImageInfo(std::string &_return,
                                   const std::string &uuid) override;
};

/**
 * @class ThriftServerCloneFactory
 * @brief `ThriftServer`工厂类
 *
 */
class ThriftServerCloneFactory : virtual public Thrift::NodeClientIfFactory {
private:
  ControlCollege *college;
  ClientPub *broadcast;

public:
  /**
   * @brief 构造函数
   *
   * @param college_ 转发`ControlCollege`对象指针
   * @param broadcast_ 广播对象
   */
  ThriftServerCloneFactory(ControlCollege *college_, ClientPub *broadcast_)
      : college(college_), broadcast(broadcast_) {}
  /**
   * @brief 析构函数
   */
  ~ThriftServerCloneFactory() override = default;
  /**
   * @brief 获取处理对象
   *
   * @param connInfo 连接信息
   * @return 处理对象指针
   */
  Thrift::NodeClientIf *
  getHandler(const ::apache::thrift::TConnectionInfo &connInfo) override;

  /**
   * @brief 释放处理程序
   *
   * @param handler 处理程序
   */
  void releaseHandler(Thrift::NodeClientIf *handler) override;
};
